<?php

class openapi_entrance extends openapi_response {

    private static $_sysParams = array();

    private static $_appParams = array();

    public function service($params) {
        // 保存请求日志
        $this->saveLog();
        // 接收所有参数
        $this->setParams($params);
        // exit;
        // 检查系统级参数
        if (! $this->checkSysParams($params)) {
            $this->send_error('e000001', self::$_sysParams['charset'], self::$_sysParams['type'], $params);
        }
        // 签名验证
        if (! $this->validate($params)) {
            $this->send_error('e000002', self::$_sysParams['charset'], self::$_sysParams['type'], $params);
        }
        // echo('<pre>');print_r(self::$_appParams);exit;
        // 检查接口是否存在
        $allow_methods = openapi_conf::getMethods();
        if (! isset($allow_methods[self::$_sysParams['class']]) || ! isset($allow_methods[self::$_sysParams['class']]['methods'][self::$_sysParams['method']])) {
            $this->send_error('e000003', self::$_sysParams['charset'], self::$_sysParams['type'], $params);
        }
        
        // 检查权限
        if (! openapi_privilege::checkAccess(self::$_sysParams['flag'], self::$_sysParams['class'], self::$_sysParams['method'])) {
            $this->send_error('e000004', self::$_sysParams['charset'], self::$_sysParams['type'], $params);
        }
        
        // 监控统计
        $statisticsLib = kernel::single('openapi_statistics');
        $statisticsLib->set(self::$_sysParams['flag'], self::$_sysParams['class'], self::$_sysParams['method']);
        
        // 实例化接口对象
        $dataObjectLib = kernel::single('openapi_object');
        if (! $dataObjectLib->instance(self::$_sysParams, self::$_appParams, $code, $sub_msg)) {
            $this->send_error($code, self::$_sysParams['charset'], self::$_sysParams['type'], $sub_msg, $params);
        }
        // 执行接口调用处理
        if ($dataObjectLib->process($result, $code, $sub_msg)) {
            $this->send_result($result, self::$_sysParams['charset'], self::$_sysParams['type']);
        } else {
            $this->send_error($code, self::$_sysParams['charset'], self::$_sysParams['type'], $sub_msg, $params);
        }
    }

    private function setParams(&$params) {
        if (empty($params)) {
            $params = array();
        }
        
        foreach ($params as &$v) {
            $v = urldecode($v);
        }
        // 兼容ESB数据
        if (empty($_POST) && ($json = file_get_contents("php://input"))) {
            $jsonArr = json_decode($json, 1);
            $_POST = $jsonArr;
        }
        return $params = array_merge($params, $_POST);
    }

    private function checkSysParams($params) {
        self::$_sysParams = array(
            'ver' => $params['ver'] ? $params['ver'] : 1,
            'charset' => $this->getFormatCharset($params['charset']) ? $params['charset'] : 'utf-8',
            'type' => $this->getFormatType($params['type']) ? $params['type'] : 'json'
        );
        
        if (empty($params['method']) || empty($params['flag']) || empty($params['sign']) || empty($params['timestamp'])) {
            return false;
        }
        
        $args = explode('.', $params['method']);
        $method = array_pop($args);
        $class = array_pop($args);
        
        if (empty($class) || empty($method)) {
            return false;
        }
        
        $path = '';
        if (count($args) > 0) {
            $path = implode('_', $args);
        }
        
        self::$_sysParams['path'] = $path;
        self::$_sysParams['flag'] = $params['flag'];
        self::$_sysParams['class'] = $class;
        self::$_sysParams['method'] = $method;
        
        return true;
    }

    private function validate($params) {
        $sign = $params['sign'];
        unset($params['sign']);
        $local_sign = $this->gen_sign($params);
        
        if ($sign != $local_sign || ! $local_sign) {
            return false;
        } else {
            unset($params['method']);
            unset($params['flag']);
            unset($params['ver']);
            unset($params['charset']);
            unset($params['type']);
            unset($params['timestamp']);
            // self::$_sysParams['sign'] = $sign;
            self::$_sysParams['task_id'] = md5($sign . microtime() . rand(10000, 99999));
            self::$_appParams = $params;
            return true;
        }
    }

    private function gen_sign($params) {
        $token = openapi_setting::getConf(self::$_sysParams['flag'], 'interfacekey');
        if (! $token) {
            return false;
        }
        return strtoupper(md5(strtoupper(md5($this->assemble($params))) . $token));
    }

    private function assemble($params) {
        if (! is_array($params))
            return null;
        ksort($params, SORT_STRING);
        $sign = '';
        foreach ($params as $key => $val) {
            if (is_null($val))
                continue;
            if (is_bool($val))
                $val = ($val) ? 1 : 0;
            $sign .= $key . (is_array($val) ? $this->assemble($val) : $val);
        }
        return $sign;
    }

    private function getSysParams() {
        return array(
            'method',
            'flag',
            'ver',
            'charset',
            'type',
            'timestamp'
        );
    }
    
    private function saveLog() {
        if (defined('LOG_FILE')) {
            $logfile = str_replace('{date}', date("Ymd"), LOG_FILE);
            $ip = ($_SERVER['REMOTE_ADDR']) ? $_SERVER['REMOTE_ADDR'] : '127.0.0.1';
            $ip = str_replace(array(
                '.',
                ':'
            ), array(
                '_',
                '_'
            ), $ip);
            $ip .= '_api';
            $logfile = str_replace('{ip}', $ip, $logfile);
        } else {
            $logfile = DATA_DIR . '/logs/all_api.php';
        }
        if (! file_exists($logfile)) {
            if (! is_dir(dirname($logfile)))
                utils::mkdir_p(dirname($logfile));
                file_put_contents($logfile, (defined(LOG_HEAD_TEXT)) ? LOG_HEAD_TEXT : '<' . '?php exit()?' . ">\n");
        }
        error_log('-------------------------------------------------------' . "\r\n", 3, $logfile);
        error_log(date('Y-m-d H:i:s') . "\r\n" . 'POST:' . var_export($_POST, 1) . "\r\n", 3, $logfile);
        error_log('JSON:' . var_export(file_get_contents("php://input"), 1) . "\r\n", 3, $logfile);
    }
}